#ifndef __REVENG_NET_SOKET_HPP__
#define __REVENG_NET_SOKET_HPP__

#include <RevEng/Object.hpp>
#include <exception>

namespace RevEng
{
	namespace Net
	{
		enum Protocol
		{
			Udp,
			Tcp,
			Protocol_Force32 = 0xFFFFFFFF
		};

		enum SocketStatus
		{
			Closed,
			Listening,
			Connected,
			SocketStatus_Force32 = 0xFFFFFFFF
		};

		//Base socket exception
		class __REVENG_EXPORT__ SocketException : public std::bad_exception
		{
		public:
			SocketException(const std::string &Message);
		};

		//Invalid socket address exception
		class __REVENG_EXPORT__ InvalidAddressException : public SocketException
		{
		protected:
			std::string m_sAddress;

		public:
			SocketException(const std::string &Message, const std::string &Address);
			std::string GetAddress() const;
		};


		//
		class __REVENG_EXPORT__  InvalidSocketCall : public SocketException
		{
		public:
			SocketException(const std::string &Message);
		};

		//Socket Class.
		class __REVENG_EXPORT__  Socket : public Object
		{
		public:
			virtual ~Socket() = 0;

			//Standard socket operations
			virtual void Connect(const std::string& Addr, UInt32 Port) = 0;
			virtual void Open(UInt32 Port, Protocol Prot) = 0;
			virtual void Listen() = 0;
			virtual Socket* Accept() = 0;
			virtual UInt32 Read(void* Data, UInt32 Size) = 0;
			virtual UInt32 Write(void* Data, UInt32 Size) = 0;
			virtual void Close() = 0;

			//Socket 'Properties'
			virtual std::string GetAddress() const = 0;
			virtual UInt32 GetPort() const = 0;
			virtual Protocol GetProtocol() const = 0;
			virtual SocketStatus GetStatus() const = 0;
			virtual bool GetBlocking() const = 0;
			virtual void SetBlocking(bool Block) = 0;
			
		public:
			static Socket* Create();
		};
	}
}

#endif	//__REVENG_NET_SOKET_HPP__
